﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Samples.WindowsAzure.ServiceManagement;
using System.IO;


namespace WAPA.Framework
{
    /// <summary>
    /// Deploys a package to a selected set of hosted services and put tasks on a queue for them to process.
    /// </summary>
    public class DeployCalculationServicesAction : IAction
    {
        public VMSizes VmSize;
        public int NoInstances;
        public DeploymentSlots DeploymentSlot;

        public HostedServiceList HostedServices;

        public DeployCalculationServicesAction()
        {
            NoInstances = 1;

            HostedServices = new HostedServiceList();
        }

        public void Execute()
        {
            CalculatePiTaskMessage workerTaskMessage = new CalculatePiTaskMessage();

            ////Set folders where all the packaging files are
            //string packagingWorkingFolder = ManagementContext.ExecutionAssemblyLocation + "\\Dependencies\\";
            ////The rolename that is mentioned in de service definition (the type that implements IRoleEntrypoint).
            //string roleName = "WAPA.Workers.PiCalculator";
            ////The location where the package should be stored
            //string packageFilePath = Path.Combine(packagingWorkingFolder, roleName + ".cspkg");

            ////Open the service definition template file. Since there is no object model or API for the definition of services, this is our only alternative.
            ////TODO:Change this as soon as the API supports deploymentupdates with new service definitions.
            //StreamReader streamReader = File.OpenText(Path.Combine(packagingWorkingFolder, "ServiceDefinition.txt"));
            //var serviceDefinition = streamReader.ReadToEnd();

            ////Don't overwrite the template but pick another file for the updated service definition 
            //string serviceDefinitionFileName = Guid.NewGuid().ToString() + ".csdef";
            //string adjustedServiceDefinitionFilePath = Path.Combine(packagingWorkingFolder, serviceDefinitionFileName);

            ////Replace the vmsize setting with the specified value
            //var serviceDefinitionWithAdjustedVMSize = serviceDefinition.Replace("vmsize=\"Small\"","vmsize=\"" + VmSize + "\"");
            //File.WriteAllText( adjustedServiceDefinitionFilePath,serviceDefinitionWithAdjustedVMSize, UTF8Encoding.UTF8);

            ////Upload the service package to a blob
            //CloudServiceManager.CreateServicePackage(@"C:\CloudCompanion\WAPerformanceAnalyser\WAPerformanceAnalyser\ServiceDefinition.csdef", roleName, ManagementContext.PiCalculatorBinariesLocation, Path.Combine(ManagementContext.PiCalculatorBinariesLocation, "WAPA.Workers.PiCalculator.dll"), packageFilePath);

            //File.Delete(adjustedServiceDefinitionFilePath);



            List<string> blockingOperations = new List<string>();

            foreach (HostedService hostedService in HostedServices)
            {
                blockingOperations.Add(ScenarioManager.DeployPiCalculatorPackage(hostedService, DeploymentSlot.ToString().ToLower(), VmSize.ToString(), NoInstances));
            }

            bool blockingOperationPending = true;

            //Wait for the background worker to pickup the related response (async call) 
            //and call the API to update the status. When the tracking gets a succeeded status
            //we can continue the next calls.
            while (blockingOperationPending)
            {
                blockingOperationPending = false;
                foreach (string trackingId in blockingOperations)
                {
                    ManagementContext.LockOperations();
                    var relatedResponse = from response in ManagementContext.Operations where (response.TrackingId == trackingId && response.TrackingId != null) select response;

                    if (relatedResponse.Count() != 1)
                    {
                        //There are one or more failed operations.
                    }
                    else if(relatedResponse.Count() == 1)
                    {
                        if (!relatedResponse.Single().Completed)
                            blockingOperationPending = true;
                    }
                    
                    ManagementContext.UnLockOperations();
                }
            }
        }
    }
}
